#ifndef _RING_QUEUE_HPP_
#define _RING_QUEUEZ_HPP

#include<iostream>
#include<vector>
#include<pthread.h>
#include"Sem.hpp"

using namespace std;

const int g_DefaultCap=6;

template <class T>
class RingQueue
{
public: 
    RingQueue(int default_num=g_DefaultCap)
    :_ring_queue(default_num)
    ,_num(default_num)
    ,_c_step(0)
    ,_p_step(0)
    ,_space_sem(default_num)
    ,_data_sem(0)
    {

    }
    void push(const T& in)
    {
        _space_sem.p();
        pthread_mutex_lock(&_plock);
        _ring_queue[_c_step++]=in;
        _c_step%=_num;
        _data_sem.v();
        pthread_mutex_unlock(&_plock);
    }
    void pop(T* out)
    {
        _data_sem.p();
        pthread_mutex_lock(&_plock);
        *out=_ring_queue[_c_step++];
        _c_step%=_num;
        _space_sem.v();
        pthread_mutex_unlock(&_plock);
    }
    ~RingQueue()
    {
        pthread_mutex_destroy(&_clock);
        pthread_mutex_destroy(&_plock);
    }
private:
    vector<T> _ring_queue;
    int _num;
    int _c_step;
    int _p_step;
    pthread_mutex_t _clock;
    pthread_mutex_t _plock;
    Sem _space_sem;
    Sem _data_sem;
};
// const int g_DefaultCap=5;

// template <class T>
// class RingQueue
// {
// public:
//     RingQueue(int default_num=g_DefaultCap)
//     :_ring_queue(default_num)
//     ,_num(default_num)
//     ,_c_step(0)
//     ,_p_step(0)
//     ,_space_sem(default_num)
//     ,_data_sem(0)
//     {
//         pthread_mutex_init(&_clock,nullptr);
//         pthread_mutex_init(&_plock,nullptr);
//     }
//     void push(const T& in)
//     {
//         _space_sem.p();
//         pthread_mutex_lock(&_plock);
//         _ring_queue[_p_step++]=in;
//         _p_step%=_num;
//         _data_sem.v();
//         pthread_mutex_unlock(&_plock); 
//     }
//     void pop(T* out)
//     {
//         _data_sem.p();
//         pthread_mutex_lock(&_clock);
//         *out=_ring_queue[_c_step++];
//         _c_step%=_num;
//         _space_sem.v();
//         pthread_mutex_unlock(&_clock);
//     }
//     ~RingQueue()
//     {
//         pthread_mutex_destroy(&_clock);
//         pthread_mutex_destroy(&_plock);
//     }
// private:
//     vector<T> _ring_queue;
//     int _num;
//     int _c_step;
//     int _p_step;
//     pthread_mutex_t _clock;
//     pthread_mutex_t _plock;
//     Sem _space_sem;
//     Sem _data_sem;
// };
// const int g_DefaultCap=5;

// template <class T>
// class RingQueue
// {
// public:
//     RingQueue(int default_num=g_DefaultCap)
//     :_ring_queue(default_num)
//     ,_num(default_num)
//     ,_c_step(0)
//     ,_p_step(0)
//     ,_space_sem(default_num)
//     ,_data_sem(0)
//     {
//         pthread_mutex_lock(&_clock);
//         pthread_mutex_lock(&_plock);
//     }
//     void push(const T& in)
//     {
//         _space_sem.p();
//         pthread_mutex_lock(&_plock);
//         _ring_queue[_p_step++]=in;
//         _p_step%=_num;
//         _data_sem.v();
//         pthread_mutex_unlock(&_plock);
//     }
//     void pop(T* out)
//     {
//         _data_sem.p();
//         pthread_mutex_lock(&_clock);
//         *out=_ring_queue[_c_step++];
//         _c_step%=_num;
//         _space_sem.v();
//         pthread_mutex_unlock(&_plock);
//     }
//     ~RingQueue()
//     {
//         pthread_mutex_destroy(&_plock);
//         pthread_mutex_destroy(&_clock);
//     }
// private:
//     vector<T> _ring_queue;
//     int _num;
//     int _c_step=0;
//     int _p_step=0;
//     pthread_mutex_t _clock;
//     pthread_mutex_t _pclok;
//     Sem _space_sem;
//     Sem _data_sem;
// };
// const int g_DefaultCap=5;
// template <class T>
// class RingQueue
// {
// public:
//     RingQueue(int default_num=g_DefaultCap)
//     :_ring_queue(default_num),
//     _num(default_num),
//     _c_step(0),
//     _p_step(0),
//     _space_sem(default_num),
//     _data_sem(0)
//     {
//         pthread_mutex_init(&clock,nullptr);
//         pthread_mutex_init(&plock,nullptr);
//     }
//     void push(const T& in)
//     {
//         _space_sem.p();
//         pthread_mutex_lock(&plcok);
//         _ring_queue[_p_step++]=in;
//         _p_step%=_num;
//         pthread_mutex_unlock(&plock);
//         _data_sem.v();
//     }
//     void pop(T* out)
//     {
//         _data_sem.p();
//         pthread_mutex_lock(&clock);
//         *out=_ring_queue[_c_step++];
//         _c_step%=_num;
//         pthread_mutex_unlock(&plock);
//         _space_sem.v();
//     }
//     ~RingQueue()
//     {
//         pthread_mutex_destroy(&clock);
//         pthread_mutex_destroy(&plock);
//     }
// private:
//     vector<T> _ring_queue;
//     int _num;
//     int _c_step;
//     int _p_step;
//     pthread_mutex_t clock;
//     pthread_mutex_t plock;
//     Sem _space_sem;
//     Sem _data_sem;
// };
// template <class T>
// class RingQueue
// {
// public:
//     RingQueue(int default_num=g_DefaultCap)
//     :_ring_queue(default_num),
//     _c_step(0),
//     _p_step(0),
//     _space_sem(default_num),
//     _data_sem(0),
//     {
//         pthread_mutex_init(&clock,nullptr);
//         pthread_mutex_init(&plock,nullptr);
//     }
//     void push(const T& in)
//     {
//         _space_sem.p();
//         pthread_mutex_lock(&plock);
//         _ring_queue[_c_step++]=in;
//         c_step%=_num;
//         pthread_mutex_destroy(&plock);
//         _data_sem.v();
//     }
//     void pop(T* out)
//     {
//         _data_sem.p();
//         pthread_mutex_lock(&clock);
//         *out=_ring_queue[_c_step++];
//         _c_step%=_num;
//         pthread_mutex_unlock(&plock);
//         _space_sem.v();
//     }
//     ~RingQueue()
//     {
//         pthread_mutex_destroy(&clock);
//         pthread_mutex_destroy(&plock);
//     }
// private:
//     vector<T> _ring_queue;
//     int _num;
//     int _c_step;
//     int _p_step;
//     pthread_mutex_t clock;
//     pthread_mutex_t plock;
//     Sem _space_sem;
//     Sem _data_sem;
// };
// template <class T>
// class RingQueue
// {
// public:
//     RingQueue(int default_num=g_DefaultCap)
//     :_ring_queue(default_num),
//     _num(default_num),
//     c_step(0),
//     p_step(0),
//     _space_sem(default_num),
//     _data_sem(0),
//     {
//         pthread_mutex_init(&_mutex,nullptr);
//         pthread_mutex_init(&_mutex,nullptr);
//     }
//     ~RingQueue()
//     {
//         pthread_mutex_destroy(&clock);
//         pthread_mutex_destroy(&plock);
//     }
//     void push(const T& in)
//     {
//         _space_sem.p();
//         pthread_mutex_lock(&plock);
//         _ring_queue[_p_step++]=in;
//         _p_step%=_num;
//         pthread_mutex_unlock(&plock);
//         _data_sem.v();
//     }
//     void pop(T* out)
//     {
//         _data_sem.p();
//         pthread_mutex_lock(&_clock);
//         *out=_ring_queue[_c_step++];
//         _c_step%=_num;
//         pthread_mutex_unlock(&clock);
//         _space_sem.v();
//     }
// private:
//     vector<T> _ring_queue;
//     int _num;
//     int c_step;
//     int p_step;
//     Sem _space_sem;
//     Sem _data_sem;
//     pthread_mutex_t clock;
//     pthread_mutex_t plock;
// };
// template <class T>
// class RingQueue
// {
// public:
//     RingQueue(int default_num=g_DefaultCap)
//     //vector在初始化的时候指定大小
//     :_ring_queue(default_num),
//     _num(default_num),
//     _c_step(0),
//     _p_step(0),
//     _space_sem(default_num)
//     _data_sem(0)
//     {
//         pthread_mutex_init(&_lock,nullptr);
//         pthread_mutex_init(&_clock,nullptr);
//     }
//     ~RingQueue()
//     {
//         pthread_mutex_destroy(&_clock);
//         pthread_mutex_destroy(&_pclock);
//     }
//     void push(const T& in)
//     {
//         //从消费者处申请空间资源
//         _space_sem.p();
//         pthread_mutex_lock(&_plock);
//         _ring_queue[_p_step++]=in;
//         _p_step%=_num;
//         pthread_mutex_unlock(&_plock);
//         //生产资源之后将数据分发给生产者
//         _data_sem.v();
//     }
//     void pop(T* out)
//     {
//         //从生产者那里申请数据资源
//         _data_sem.p();
//         pthread_mutex_lock(&_mutex);
//         *out=_ring_queue[_c_step++];
//         _c_step%=_num;
//         pthread_mutex_unlock(&_clock);
//         //获得资源之后将空间资源分发给生产者
//         _space_sem.v();
//     }
// private:
//     vector<T> _ring_queue;
//     int _num;
//     int _c_step;
//     int _p_step;
//     Sem _space_sem;
//     Sem _data_sem;
//     pthread_mutex_t clock;
//     pthread_mutex_t plock;
// };

#endif